home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-02-03 | 31.7 KB | 1,596 lines |
- Path: xanth!nic.MR.NET!csd4.milw.wisc.edu!leah!itsgw!steinmetz!uunet!allbery
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Newsgroups: comp.sources.misc
- Subject: v06i024: shadow password routines, part 3 of ???
- Message-ID: <47756@uunet.UU.NET>
- Date: 29 Jan 89 21:14:21 GMT
- Sender: allbery@uunet.UU.NET
- Reply-To: jfh@hal.CWRU.Edu@convex.UUCP (John F. Haugh II)
- Lines: 1584
- Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 6, Issue 24
- Submitted-by: jfh@hal.CWRU.Edu@convex.UUCP (John F. Haugh II)
- Archive-name: shadow-2.pt3
-
- [See part 1 for information (part 2 for my lament). ++bsa]
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # lastlog.h
- # login.c
- # motd.c
- # password.c
- # shell.c
- # utmp.c
- # age.c
- # env.c
- # pwent.c
- # shadow.c
- # valid.c
- # lmain.c
- # smain.c
- # pwconv.c
- # dialup.c
- # dialchk.c
- # pwunconv.c
- # This archive created: Sun Jan 22 22:24:55 1989
- # By: John F. Haugh II (River Parishes Programming, Dallas TX)
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'lastlog.h'
- then
- echo shar: "will not over-write existing file 'lastlog.h'"
- else
- cat << \SHAR_EOF > 'lastlog.h'
- /*
- * lastlog.h - structure of lastlog file
- *
- * This file defines a lastlog file structure which should be sufficient
- * to hold the information required by login. It should only be used if
- * there is no real lastlog.h file.
- */
-
- struct lastlog {
- time_t ll_time;
- char ll_line[8];
- };
- SHAR_EOF
- fi
- if test -f 'login.c'
- then
- echo shar: "will not over-write existing file 'login.c'"
- else
- cat << \SHAR_EOF > 'login.c'
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
-
- void setenv ();
-
- void login (name)
- char *name;
- {
- char buf[BUFSIZ];
- char *envp[32];
- int envc;
- char *cp;
- int i;
-
- memset (buf, 0, BUFSIZ);
-
- fputs ("login: ", stdout);
-
- if (fgets (buf, BUFSIZ, stdin) != buf)
- exit (1);
-
- buf[strlen (buf) - 1] = '\0'; /* remove \n [ must be there ] */
-
- for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
- ;
-
- for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++)
- ;
-
- if (*cp)
- cp++;
-
- name[i] = '\0';
-
- if (*cp != '\0') { /* process new variables */
- for (envc = 0;envc < 32;envc++) {
- envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,");
-
- if (envp[envc] == (char *) 0)
- break;
- }
- setenv (envc, envp);
- }
- }
- SHAR_EOF
- fi
- if test -f 'motd.c'
- then
- echo shar: "will not over-write existing file 'motd.c'"
- else
- cat << \SHAR_EOF > 'motd.c'
- #include <stdio.h>
- #include <string.h>
- #include "config.h"
-
- extern char home[];
-
- void motd ()
- {
- #ifdef MOTD
- FILE *fp;
- register int c;
- #ifdef HUSHLOGIN
- char hush[BUFSIZ];
-
- (void) strcat (strcpy (hush, home + 5), "/.hushlogin");
-
- if (access (hush, 0) == 0)
- return;
- #endif
- if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0)
- return;
-
- while ((c = getc (fp)) != EOF)
- putchar (c);
-
- fclose (fp);
- fflush (stdout);
- #endif
- }
- SHAR_EOF
- fi
- if test -f 'password.c'
- then
- echo shar: "will not over-write existing file 'password.c'"
- else
- cat << \SHAR_EOF > 'password.c'
- #include <stdio.h>
- #include <string.h>
- #include <termio.h>
- #include <fcntl.h>
-
- /*
- * password - prompt for password and return entry
- *
- * Need to fake up getpass(). Returns TRUE if a password
- * was successfully input, and FALSE otherwise, including
- * EOF on input or ioctl() failure. pass is not modified
- * on failure.
- */
-
- int password (prompt, pass)
- char *prompt;
- char *pass;
- {
- char buf[BUFSIZ];
- int eof;
- int ttyopened = 0;
- struct termio termio;
- struct termio save;
- FILE *fp;
-
- if ((fp = fopen ("/dev/tty", "r")) == (FILE *) 0)
- fp = stdin;
- else
- ttyopened = 1;
-
- if (ioctl (fileno (fp), TCGETA, &termio))
- return (0);
-
- save = termio;
- termio.c_lflag &= ~ECHO;
- ioctl (fileno (fp), TCSETAF, &termio);
-
- fputs (prompt, stdout);
- eof = gets (buf) == (char *) 0 || feof (fp) || ferror (fp);
- putchar ('\n');
-
- ioctl (fileno (fp), TCSETAF, &save);
-
- if (! eof) {
- buf[8] = '\0';
- (void) strcpy (pass, buf);
- }
- if (ttyopened)
- fclose (fp);
-
- return (! eof);
- }
- SHAR_EOF
- fi
- if test -f 'shell.c'
- then
- echo shar: "will not over-write existing file 'shell.c'"
- else
- cat << \SHAR_EOF > 'shell.c'
- #include <stdio.h>
- #include <string.h>
- #include "config.h"
-
- extern char *newenvp[];
-
- void shell (file)
- char *file;
- {
- char arg0[BUFSIZ];
- #ifndef SU
- char *path;
- #endif
- char *strrchr ();
- extern int errno;
-
- if (file == (char *) 0)
- exit (1);
-
- #ifndef SU
- if (path = strrchr (file, '/'))
- path++;
- else
- path = file;
-
- (void) strcpy (arg0 + 1, path);
- arg0[0] = '-';
- #else
- (void) strcpy (arg0, "-su");
- #endif
- #ifndef NDEBUG
- printf ("Executing shell %s\n", file);
- #endif
- execle (file, arg0, (char *) 0, newenvp);
- printf ("Can't execute %s\n", file);
- exit (errno);
- }
- SHAR_EOF
- fi
- if test -f 'utmp.c'
- then
- echo shar: "will not over-write existing file 'utmp.c'"
- else
- cat << \SHAR_EOF > 'utmp.c'
- #include <sys/types.h>
- #include <utmp.h>
- #include <string.h>
- #include <stdio.h>
- #include "config.h"
-
- extern struct utmp utent;
- extern char name[];
-
- struct utmp *getutent ();
- void setutent ();
- void endutent ();
- void pututline ();
- char *memset ();
- time_t time ();
-
- void checkutmp ()
- {
- struct utmp *ut;
- #ifndef NDEBUG
- int pid = getppid ();
- #else
- int pid = getpid ();
- #endif
- setutent ();
-
- while (ut = getutent ())
- if (ut->ut_pid == pid)
- break;
-
- if (ut)
- utent = *ut;
-
- endutent ();
-
- if (ut && utent.ut_pid == pid)
- return;
-
- puts ("No utmp entry. You must exec \"login\" from the lowest level \"sh\"");
- exit (1);
- }
-
- void setutmp ()
- {
- FILE *wtmp;
- char tty[sizeof utent.ut_line + 1];
- char *line;
-
- setutent ();
-
- (void) strncpy (utent.ut_user, name, sizeof utent.ut_user);
-
- utent.ut_type = USER_PROCESS;
-
- if (line = strrchr (utent.ut_line, '/')) {
- (void) strcpy (tty, line + 1);
- (void) memset (utent.ut_line, '\0', sizeof utent.ut_line);
- (void) strcpy (utent.ut_line, tty);
- }
- (void) time (&utent.ut_time);
-
- pututline (&utent);
- endutent ();
-
- if ((wtmp = fopen (WTMP_FILE, "a+"))) {
- fwrite (&utent, sizeof utent, 1, wtmp);
- fclose (wtmp);
- }
- }
- SHAR_EOF
- fi
- if test -f 'age.c'
- then
- echo shar: "will not over-write existing file 'age.c'"
- else
- cat << \SHAR_EOF > 'age.c'
- #include <sys/types.h>
- #include <stdio.h>
- #include <pwd.h>
- #include "config.h"
-
- #ifndef PASSWD
- extern char *newenvp[];
- #endif
-
- time_t time ();
-
- #ifdef AGING
- #ifdef PASSWD
- char *l64a (l)
- long l;
- {
- static char buf[8];
- int i = 0;
-
- if (i < 0L)
- return ((char *) 0);
-
- do {
- buf[i++] = i64c ((int) (l % 64));
- buf[i] = '\0';
- } while (l /= 64L, l > 0 && i < 6);
-
- return (buf);
- }
- #endif
- int i64c (i)
- int i;
- {
- if (i < 0)
- return ('.');
- else if (i > 63)
- return ('z');
-
- if (i == 0)
- return ('.');
-
- if (i == 1)
- return ('/');
-
- if (i >= 2 && i <= 11)
- return ('0' - 2 + i);
-
- if (i >= 12 && i <= 37)
- return ('A' - 12 + i);
-
- if (i >= 38 && i <= 63)
- return ('a' - 38 + i);
-
- return ('\0');
- }
-
- int c64i (c)
- char c;
- {
- if (c == '.')
- return (0);
-
- if (c == '/')
- return (1);
-
- if (c >= '0' && c <= '9')
- return (c - '0' + 2);
-
- if (c >= 'A' && c <= 'Z')
- return (c - 'A' + 12);
-
- if (c >= 'a' && c <= 'z')
- return (c - 'a' + 38);
- else
- return (-1);
- }
-
- long a64l (s)
- char *s;
- {
- int i;
- long value;
- long shift = 0;
-
- for (i = 0, value = 0L;i < 6 && *s;s++) {
- value += (c64i (*s) << shift);
- shift += 6;
- }
- return (value);
- }
- #ifndef PASSWD
- void expire (age)
- char *age;
- {
- long clock;
- long week;
- extern char name[];
- extern int errno;
-
- (void) time (&clock);
- clock /= (7L * 24L * 60L * 60L);
-
- if (strlen (age) < 4)
- week = 0L;
- else
- week = a64l (age + 2);
-
- if (clock >= week + c64i (age[0])) {
- printf ("Your password has expired.");
-
- if (c64i (age[0]) < c64i (age[1])) {
- puts (" Contact the system administrator.\n");
- exit (1);
- }
- puts (" Choose a new one.\n");
-
- execl ("/bin/passwd", "-passwd", name, (char *) 0);
- puts ("Can't execute /bin/passwd");
- exit (errno);
- }
- }
- #endif
- #endif
- SHAR_EOF
- fi
- if test -f 'env.c'
- then
- echo shar: "will not over-write existing file 'env.c'"
- else
- cat << \SHAR_EOF > 'env.c'
- #include <stdio.h>
- #include <string.h>
-
- extern char **environ;
- extern char *newenvp[];
- extern int newenvc;
- extern int maxenv;
-
- char *strdup ();
- void free ();
-
- static char *forbid[] = {
- "HOME",
- "IFS",
- "PATH",
- "SHELL",
- (char *) 0
- };
-
- void addenv (entry)
- char *entry;
- {
- char *cp;
- int i;
- int len;
-
- if (cp = strchr (entry, '='))
- len = cp - entry;
- else
- len = strlen (entry);
-
- for (i = 0;i < newenvc;i++)
- if (strncmp (entry, newenvp[i], len) == 0 &&
- (newenvp[i][len] == '=' || newenvp[i][len] == '\0'))
- break;
-
- if (i == maxenv) {
- puts ("Environment overflow");
- return;
- }
- if (i == newenvc) {
- newenvp[newenvc++] = strdup (entry);
- } else {
- free (newenvp[i]);
- newenvp[i] = strdup (entry);
- }
- }
-
- void setenv (argc, argv)
- int argc;
- char **argv;
- {
- int i;
- int n;
- char variable[BUFSIZ];
- char *cp;
-
- for (i = 0;i < argc;i++) {
- if ((n = strlen (argv[i])) >= BUFSIZ)
- continue; /* ignore long entries */
-
- if (! (cp = strchr (argv[i], '='))) {
- (void) strcpy (variable, argv[i]);
- } else {
- (void) strncpy (variable, argv[i], cp - argv[i]);
- variable[cp - argv[i]] = '\0';
- }
- for (n = 0;forbid[n] != (char *) 0;n++)
- if (strcmp (variable, forbid[n]) == 0)
- break;
-
- if (forbid[n] != (char *) 0) {
- printf ("You may not change $%s\n", forbid[n]);
- continue;
- }
- addenv (argv[i]);
- }
- }
- SHAR_EOF
- fi
- if test -f 'pwent.c'
- then
- echo shar: "will not over-write existing file 'pwent.c'"
- else
- cat << \SHAR_EOF > 'pwent.c'
- #include <stdio.h>
- #include <pwd.h>
- #include <string.h>
-
- #define SBUFSIZ 64
-
- static char *tokcpy (buf, token)
- char *buf;
- char *token;
- {
- static char *cp;
- char *start;
-
- if (buf == (char *) 0)
- buf = cp;
- else
- cp = buf;
-
- start = cp;
-
- if (*buf == '\0')
- return ((char *) 0);
-
- while (*buf && *buf != ':')
- *token++ = *buf++;
-
- *token = '\0';
-
- if (*buf)
- cp = buf + 1;
-
- return (start);
- }
-
- struct passwd *sgetpwent (buf)
- char *buf;
- {
- static struct passwd pwent;
- static char name[SBUFSIZ];
- static char password[SBUFSIZ];
- static char gecos[SBUFSIZ];
- static char home[SBUFSIZ];
- static char shell[SBUFSIZ];
- static char age[SBUFSIZ];
- char tmp[BUFSIZ];
- char *cp;
-
- pwent.pw_name = name;
- pwent.pw_passwd = password;
- pwent.pw_uid = -1;
- pwent.pw_gid = -1;
- pwent.pw_age = age;
- pwent.pw_comment = (char *) 0;
- pwent.pw_gecos = gecos;
- pwent.pw_dir = home;
- pwent.pw_shell = shell;
-
- (void) strcpy (tmp, buf);
-
- if (! tokcpy (tmp, name) || ! name[0])
- return ((struct passwd *) 0);
-
- if (! tokcpy ((char *) 0, password))
- return ((struct passwd *) 0);
-
- if (tokcpy ((char *) 0, tmp) && *tmp)
- pwent.pw_uid = atoi (tmp);
- else
- return ((struct passwd *) 0);
-
- if (tokcpy ((char *) 0, tmp) && *tmp)
- pwent.pw_gid = atoi (tmp);
- else
- return ((struct passwd *) 0);
-
- if (cp = strchr (password, ',')) {
- (void) strcpy (age, cp + 1);
- *cp = '\0';
- } else
- pwent.pw_age = (char *) 0;
-
- if (! tokcpy ((char *) 0, gecos))
- return ((struct passwd *) 0);
-
- if (! tokcpy ((char *) 0, home))
- return ((struct passwd *) 0);
-
- if (! tokcpy ((char *) 0, shell) && *shell)
- pwent.pw_shell = (char *) 0;
-
- if (pwent.pw_passwd && pwent.pw_passwd[0] == '\0')
- pwent.pw_passwd = (char *) 0;
-
- return (&pwent);
- }
- #ifdef FGETPWENT
- struct passwd *fgetpwent (fp)
- FILE *fp;
- {
- char buf[BUFSIZ];
-
- while (fgets (buf, BUFSIZ, fp) != (char *) 0) {
- if (buf[0] == '#')
- continue;
-
- buf[strlen (buf) - 1] = '\0';
- return (sgetpwent (buf));
- }
- return ((struct passwd *) 0);
- }
- #endif
- SHAR_EOF
- fi
- if test -f 'shadow.c'
- then
- echo shar: "will not over-write existing file 'shadow.c'"
- else
- cat << \SHAR_EOF > 'shadow.c'
- #include "shadow.h"
- #include <stdio.h>
- #include <string.h>
-
- static FILE *shadow;
-
- void setspent ()
- {
- if (shadow)
- rewind (shadow);
- else
- shadow = fopen (SHADOW, "r");
- }
-
- void endspent ()
- {
- if (shadow)
- (void) fclose (shadow);
-
- shadow = (FILE *) 0;
- }
-
- struct spwd *fgetspent (fp)
- FILE *fp;
- {
- static struct spwd spwd;
- static char name[32];
- static char pass[32];
- char buf[BUFSIZ];
- char *cp;
- int atoi ();
- long atol ();
-
- if (! fp)
- return (0);
-
- if (fgets (buf, BUFSIZ, fp) == (char *) 0)
- return (0);
-
- buf[strlen (buf) - 1] = '\0';
-
- if ((cp = strtok (buf, ":")) && *cp)
- (void) strcpy (name, cp);
- else
- return (0);
-
- if ((cp = strtok ((char *) 0, ":")) && *cp)
- (void) strcpy (pass, cp);
- else
- return (0);
-
- if ((cp = strtok ((char *) 0, ":")) && *cp)
- spwd.sp_lstchg = atol (cp);
- else
- return (0);
-
- if ((cp = strtok ((char *) 0, ":")) && *cp)
- spwd.sp_min = atoi (cp);
- else
- return (0);
-
- if ((cp = strtok ((char *) 0, ":")) && *cp)
- spwd.sp_max = atoi (cp);
- else
- return (0);
-
- spwd.sp_namp = name;
- spwd.sp_pwdp = pass;
-
- return (&spwd);
- }
-
- struct spwd *getspent ()
- {
- if (! shadow)
- setspent ();
-
- return (fgetspent (shadow));
- }
-
- struct spwd *getspnam (name)
- char *name;
- {
- struct spwd *spwd;
-
- setspent ();
-
- while ((spwd = getspent ()) != (struct spwd *) 0) {
- if (strcmp (name, spwd->sp_namp) == 0)
- return (spwd);
- }
- return (0);
- }
-
- int putspent (spwd, fp)
- struct spwd *spwd;
- FILE *fp;
- {
- if (! fp)
- return (0);
-
- return (fprintf (fp, "%s:%s:%ld:%d:%d\n",
- spwd->sp_namp, spwd->sp_pwdp,
- spwd->sp_lstchg, spwd->sp_min, spwd->sp_max) != EOF);
- }
- SHAR_EOF
- fi
- if test -f 'valid.c'
- then
- echo shar: "will not over-write existing file 'valid.c'"
- else
- cat << \SHAR_EOF > 'valid.c'
- #include <pwd.h>
-
- /*
- * valid - compare encrypted passwords
- *
- * Valid() compares the DES encrypted password from the password file
- * against the password which the user has entered after it has been
- * encrypted using the same salt as the original.
- */
-
- int valid (password, entry)
- char *password;
- struct passwd *entry;
- {
- char *encrypt;
- char *salt;
- char *crypt ();
-
- /*
- * Start with blank or empty password entries. Always encrypt
- * a password if no such user exists. Only if the ID exists and
- * the password is really empty do you return quickly. This
- * routine is meant to waste CPU time.
- */
-
- if (entry->pw_name &&
- (entry->pw_passwd == (char *) 0 ||
- strlen (entry->pw_passwd) == 0)) {
- if (strlen (password) == 0)
- return (1); /* user entered nothing */
- else
- return (0); /* user entered something! */
- }
-
- /*
- * If there is no entry then we need a salt to use.
- */
-
- if (entry->pw_passwd == (char *) 0 || entry->pw_passwd[0] == '\0')
- salt = "xx";
- else
- salt = entry->pw_passwd;
-
- /*
- * Now, perform the encryption using the salt from before on
- * the users input. Since we always encrypt the string, it
- * should be very difficult to determine if the user exists by
- * looking at execution time.
- */
-
- encrypt = crypt (password, salt);
-
- /*
- * One last time we must deal with there being no password file
- * entry for the user. We use the pw_passwd == NULL idiom to
- * cause non-existent users to not be validated. Even still,
- * we are safe because if the string were == "", any encrypted
- * string is not going to match - the output of crypt() begins
- * with the salt, which is "xx", not "".
- */
-
- if (entry->pw_passwd && strcmp (encrypt, entry->pw_passwd) == 0)
- return (1);
- else
- return (0);
- }
- SHAR_EOF
- fi
- if test -f 'lmain.c'
- then
- echo shar: "will not over-write existing file 'lmain.c'"
- else
- cat << \SHAR_EOF > 'lmain.c'
- #include <sys/types.h>
- #include <stdio.h>
- #include <pwd.h>
- #include <utmp.h>
- #include <time.h>
- #include <string.h>
- #include <signal.h>
- #include "config.h"
- #include "lastlog.h"
-
- char name[BUFSIZ];
- char pass[BUFSIZ];
- char home[BUFSIZ];
- char prog[BUFSIZ];
- char mail[BUFSIZ];
-
- struct passwd pwent;
- struct utmp utent;
- struct lastlog lastlog;
-
- #ifndef MAXENV
- #define MAXENV 64
- #endif
-
- char *newenvp[MAXENV];
- int newenvc = 0;
- int maxenv = MAXENV;
- extern char **environ;
-
- char *getenv ();
- char *memset ();
- void checkutmp ();
- void addenv ();
- void setenv ();
- unsigned alarm ();
- void login ();
- void entry ();
- void setutmp ();
- void subsystem ();
- void log ();
- void setup ();
- void expire ();
- void motd ();
- void mailcheck ();
- void shell ();
-
- #ifndef ALARM
- #define ALARM 60
- #endif
-
- #ifndef RETRIES
- #define RETRIES 3
- #endif
-
- int main (argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
- {
- int retries = RETRIES;
-
- checkutmp (); /* must be lowest level shell */
-
- if (! isatty (0)) /* must be a terminal */
- exit (1);
-
- while (*envp) /* add inherited environment, */
- addenv (*envp++); /* some variables change later */
-
- #ifdef TZ
- addenv (TZ); /* set the default $TZ, if one */
- #endif
- #ifdef HZ
- addenv (HZ); /* set the default $HZ, if one */
- #endif
- if (argc >= 2) { /* now set command line variables */
- setenv (argc - 2, &argv[2]);
- (void) strncpy (name, argv[1], sizeof name);
- }
- (void) alarm (ALARM); /* only allow ALARM sec. for login */
-
- while (1) { /* repeatedly get login/password pairs */
- if (! name[0]) { /* need to get a login id */
- login (name);
- continue;
- }
- entry (name, &pwent); /* get entry from password file */
-
- /*
- * Here we have a sticky situation. Some accounts may have no
- * password entry in the password file. So, we don't ask for a
- * password. Others, have a blank password entered - you be the
- * judge. The conditional compilation NOBLANK requires even
- * blank passwords to be prompted for. This may well break
- * quite a few systems. Use with discretion.
- */
-
- #ifdef NOBLANK
- /* get a password from user */
- if (! password ("Password:", pass))
- continue;
- #else
- if ((! pwent.pw_name || pwent.pw_passwd)
- && ! password ("Password:", pass))
- continue;
- #endif
- if (valid (pass, &pwent)) /* check encrypted passwords ... */
- break; /* ... encrypted passwords matched */
-
- if (--retries <= 0) /* only allow so many failures */
- exit (1);
-
- puts ("Login incorrect");
- (void) memset (name, '\0', sizeof name);
- }
- #ifdef DIALUP
- if (! dialcheck (utent.ut_line,
- pwent.pw_shell ? pwent.pw_shell:"/bin/sh")) {
- puts ("Dialup password incorrect");
- exit (1);
- }
- #endif
- (void) alarm (0); /* turn off alarm clock */
- environ = newenvp; /* make new environment active */
-
- if (getenv ("IFS")) /* don't export user IFS ... */
- addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
-
- setutmp (); /* make entry in utmp & wtmp files */
- #ifdef CONSOLE
- if (pwent.pw_uid == 0 && /* root no logging in on console ? */
- strncmp (CONSOLE, utent.ut_line, sizeof utent.ut_line))
- exit (1); /* then exit! */
- #endif
- if (pwent.pw_shell[0] == '*') /* subsystem root required */
- subsystem (); /* figure out what to execute */
-
- #ifdef LASTLOG
- log (); /* give last login and log this one */
- #endif
- setup (&pwent); /* set UID, GID, HOME, etc ... */
- #ifdef AGING
- if (pwent.pw_age) /* check for age of password ... */
- expire (pwent.pw_age); /* ... ask for new one if expired */
- #endif
- #ifdef MOTD
- motd (); /* print the message of the day */
- #endif
- #ifdef LASTLOG
- if (lastlog.ll_time != 0)
- printf ("Last login: %.19s on %s\n",
- ctime (&lastlog.ll_time), lastlog.ll_line);
- #endif
- #ifdef MAILCHECK
- mailcheck (); /* report on the status of mail */
- #endif
- signal (SIGINT, SIG_DFL); /* default interrupt signal */
- signal (SIGQUIT, SIG_DFL); /* default quit signal */
- signal (SIGTERM, SIG_DFL); /* default terminate signal */
- signal (SIGALRM, SIG_DFL); /* default alarm signal */
-
- shell (pwent.pw_shell); /* exec the shell finally. */
- /*NOTREACHED*/
- }
- SHAR_EOF
- fi
- if test -f 'smain.c'
- then
- echo shar: "will not over-write existing file 'smain.c'"
- else
- cat << \SHAR_EOF > 'smain.c'
- #include <sys/types.h>
- #include <stdio.h>
- #include <pwd.h>
- #include <string.h>
- #include <signal.h>
- #include "config.h"
- #include "lastlog.h"
-
- #ifndef MAXENV
- #define MAXENV 64
- #endif
-
- char name[BUFSIZ];
- char pass[BUFSIZ];
- char home[BUFSIZ];
- char prog[BUFSIZ];
- char mail[BUFSIZ];
- char oldname[BUFSIZ];
- char *newenvp[MAXENV];
- int newenvc = 0;
- int maxenv = MAXENV;
- struct passwd pwent;
-
- void addenv ();
- void entry ();
- void sulog ();
- void subsystem ();
- void setup ();
- void motd ();
- void mailcheck ();
- void shell ();
-
- extern char **environ;
-
- int main (argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
- {
- char *getenv ();
- int doshell;
- int fakelogin = 0;
- int amroot;
- struct passwd *pw;
- struct passwd *getpwuid ();
-
- while (*envp) /* add inherited environment, */
- addenv (*envp++); /* some variables change later */
-
- #ifdef TZ
- addenv (TZ); /* set the default $TZ, if one */
- #endif
- #ifdef HZ
- addenv (HZ); /* set the default $HZ, if one */
- #endif
- argc--; argv++; /* shift out command name */
-
- if (argc > 0 && argv[0][0] == '-' && argv[0][1] == '\0') {
- fakelogin = 1;
- argc--; argv++; /* shift ... */
- }
- if (argc > 0 && argv[0][0] != '-') {
- (void) strcpy (name, argv[0]); /* use this login id */
- argc--; argv++; /* shift ... */
- }
- doshell = argc == 0; /* any arguments remaining? */
-
- if (pw = getpwuid (getuid ())) /* need old user name */
- (void) strcpy (oldname, pw->pw_name);
- else /* user ID MUST exist */
- goto failure;
-
- amroot = getuid () == 0; /* currently am super user */
-
- if (! name[0]) /* use default user ID */
- (void) strcpy (name, "root");
-
- entry (name, &pwent); /* get password file entry */
-
- if (pwent.pw_name == (char *) 0) { /* unknown user */
- (void) fprintf (stderr, "Unknown id: %s\n", pwent.pw_name);
- exit (1);
- }
-
- /*
- * Here we have a sticky situation. Some accounts may have no
- * password entry in the password file. So, we don't ask for a
- * password. Others, have a blank password entered - you be the
- * judge. The conditional compilation NOBLANK requires even
- * blank passwords to be prompted for. This may well break
- * quite a few systems. Use with discretion.
- */
-
- #ifdef NOBLANK
- if (! amroot && ! password ("Password:", pass))
- goto failure;
- #else
- if (! amroot && (pwent.pw_name == (char *) 0 || pwent.pw_passwd)
- && ! password ("Password:", pass))
- goto failure;
- #endif
- /* check encrypted passwords ... */
- if (! amroot && ! valid (pass, &pwent)) {
- failure: sulog (0); /* log failed attempt */
- puts ("Sorry.");
- exit (1);
- }
- #ifdef SULOG
- sulog (1); /* save SU information */
- #endif
- if (pwent.pw_uid == 0)
- addenv (SUPATH);
- else
- addenv (PATH);
-
- environ = newenvp; /* make new environment active */
-
- if (getenv ("IFS")) /* don't export user IFS ... */
- addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
-
- if (doshell && pwent.pw_shell[0] == '*') /* subsystem root required */
- subsystem (); /* figure out what to execute */
-
- if (fakelogin)
- setup (&pwent); /* set UID, GID, HOME, etc ... */
- else {
- if (setgid (pwent.pw_gid) || setuid (pwent.pw_uid)) {
- perror ("Can't set ID");
- exit (1);
- }
- }
- if (! doshell) { /* execute arguments as command */
- if (! pwent.pw_shell)
- pwent.pw_shell = "/bin/sh";
-
- argv[-1] = pwent.pw_shell;
- (void) execv (pwent.pw_shell, &argv[-1]);
- (void) fprintf (stderr, "No shell\n");
- exit (1);
- }
- if (fakelogin) {
- #ifdef MOTD
- motd (); /* print the message of the day */
- #endif
- #ifdef MAILCHECK
- mailcheck (); /* report on the status of mail */
- #endif
- shell (pwent.pw_shell); /* exec the shell finally. */
- } else {
- if (pwent.pw_shell == (char *) 0)
- pwent.pw_shell = "/bin/sh";
-
- execl (pwent.pw_shell, "su", (char *) 0);
- perror (pwent.pw_shell);
- exit (1);
- }
- /*NOTREACHED*/
- }
- SHAR_EOF
- fi
- if test -f 'pwconv.c'
- then
- echo shar: "will not over-write existing file 'pwconv.c'"
- else
- cat << \SHAR_EOF > 'pwconv.c'
- /*
- * pwconv - convert and update shadow password files
- *
- * Pwconv copies the old password file information to a new shadow
- * password file, merging entries from an optional existing shadow
- * file.
- *
- * The new password file is left in npasswd, the new shadow file is
- * left in nshadow. Existing shadow entries are copied as is.
- * New entries are created with passwords which expire in 10000 days,
- * with a last changed date of today, unless password aging
- * information was already present. Entries with blank passwords
- * are not copied to the shadow file at all.
- */
-
- #include <sys/types.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <pwd.h>
- #include "config.h"
- #include "lastlog.h"
- #include "shadow.h"
-
- char buf[BUFSIZ];
-
- long time ();
- long a64l ();
-
- int main ()
- {
- long today;
- struct passwd *pw;
- struct passwd *sgetpwent ();
- FILE *pwd;
- FILE *npwd;
- FILE *shadow;
- struct spwd *spwd;
- struct spwd tspwd;
- int fd;
-
- if (! (pwd = fopen (PWDFILE, "r"))) {
- perror (PWDFILE);
- return (1);
- }
- unlink ("npasswd");
- if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
- ! (npwd = fdopen (fd, "w"))) {
- perror ("npasswd");
- return (1);
- }
- unlink ("nshadow");
- if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
- ! (shadow = fdopen (fd, "w"))) {
- perror ("nshadow");
- return (1);
- }
-
- (void) time (&today);
- today /= (24L * 60L * 60L);
-
- while (fgets (buf, BUFSIZ, pwd) == buf) {
- buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
-
- if (buf[0] == '#') { /* comment line */
- (void) fprintf (npwd, "%s\n", buf);
- continue;
- }
- if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
- (void) fprintf (npwd, "%s\n", buf);
- continue;
- }
- if (pw->pw_passwd == (char *) 0) { /* no password, skip */
- (void) fprintf (npwd, "%s\n", buf);
- continue;
- }
- setspent (); /* rewind old shadow file */
-
- if (spwd = getspnam (pw->pw_name)) {
- if (! putspent (spwd, shadow)) { /* copy old entry */
- perror ("nshadow");
- return (1);
- }
- } else { /* need a new entry. */
- tspwd.sp_namp = pw->pw_name;
- tspwd.sp_pwdp = pw->pw_passwd;
- pw->pw_passwd = "x";
-
- if (pw->pw_age) { /* copy old password age stuff */
- tspwd.sp_min = c64i (pw->pw_age[1]);
- tspwd.sp_max = c64i (pw->pw_age[0]);
- if (strlen (pw->pw_age) == 4)
- tspwd.sp_lstchg = a64l (&pw->pw_age[2]);
- else
- tspwd.sp_lstchg = 0L;
-
- /*
- * Convert weeks to days
- */
-
- tspwd.sp_min *= 7;
- tspwd.sp_max *= 7;
- tspwd.sp_lstchg *= 7;
- } else { /* fake up new password age stuff */
- tspwd.sp_max = 10000;
- tspwd.sp_min = 0;
- tspwd.sp_lstchg = today;
- }
- if (! putspent (&tspwd, shadow)) { /* output entry */
- perror ("nshadow");
- return (1);
- }
- }
- (void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:",
- pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
- pw->pw_uid, pw->pw_gid,
- pw->pw_gecos, pw->pw_dir);
-
- if (fprintf (npwd, "%s\n",
- pw->pw_shell ? pw->pw_shell:"") == EOF) {
- perror ("npasswd");
- return (1);
- }
- }
- endspent ();
-
- if (ferror (npwd) || ferror (shadow)) {
- perror ("pwconv");
- (void) unlink ("npasswd");
- (void) unlink ("nshadow");
- }
- (void) fclose (pwd);
- (void) fclose (npwd);
- (void) fclose (shadow);
-
- return (0);
- }
- SHAR_EOF
- fi
- if test -f 'dialup.c'
- then
- echo shar: "will not over-write existing file 'dialup.c'"
- else
- cat << \SHAR_EOF > 'dialup.c'
- #include <stdio.h>
- #include <string.h>
- #include "dialup.h"
-
- static FILE *dialpwd;
-
- void setduent ()
- {
- if (dialpwd)
- rewind (dialpwd);
- else
- dialpwd = fopen (DIALPWD, "r");
- }
-
- void endduent ()
- {
- if (dialpwd)
- fclose (dialpwd);
-
- dialpwd = (FILE *) 0;
- }
-
- struct dialup *getduent ()
- {
- static struct dialup dialup; /* static structure to point to */
- static char shell[64]; /* some space for a login shell */
- static char passwd[16]; /* some space for dialup password */
- char buf[BUFSIZ];
- char *cp;
-
- if (! dialpwd)
- setduent ();
-
- if (! dialpwd || feof (dialpwd))
- return ((struct dialup *) 0);
-
- while (fgets (buf, BUFSIZ, dialpwd) == buf)
- if (buf[0] == '#')
- continue;
-
- if (feof (dialpwd))
- return ((struct dialup *) 0);
-
- cp = strchr (buf, ':');
- if (cp - buf > sizeof shell) /* something is fishy ... */
- return ((struct dialup *) 0);
-
- (void) strncpy (shell, buf, cp - buf);
- shell[cp - buf] = '\0';
-
- if (strlen (cp + 1) > sizeof passwd) /* something is REALLY fishy */
- return ((struct dialup *) 0);
-
- (void) strcpy (passwd, cp + 1);
- passwd[strlen (passwd) - 1] = '\0';
- if (cp = strchr (passwd, ':'))
- *cp = '\0';
-
- dialup.du_shell = shell;
- dialup.du_passwd = passwd;
-
- return (&dialup);
- }
-
- struct dialup *getdushell (shell)
- char *shell;
- {
- struct dialup *dialup;
-
- while (dialup = getduent ())
- if (strcmp (shell, dialup->du_shell) == 0)
- return (dialup);
-
- return ((struct dialup *) 0);
- }
-
- int isadialup (tty)
- char *tty;
- {
- FILE *fp;
- char buf[BUFSIZ];
- int dialup = 0;
-
- if (! (fp = fopen (DIALUPS, "r")))
- return (0);
-
- while (fgets (buf, BUFSIZ, fp) == buf) {
- buf[strlen (buf) - 1] = '\0';
-
- if (strcmp (buf, tty) == 0) {
- dialup = 1;
- break;
- }
- }
- fclose (fp);
-
- return (dialup);
- }
- SHAR_EOF
- fi
- if test -f 'dialchk.c'
- then
- echo shar: "will not over-write existing file 'dialchk.c'"
- else
- cat << \SHAR_EOF > 'dialchk.c'
- #include <stdio.h>
- #include "config.h"
- #include "dialup.h"
-
- /*
- * Check for dialup password
- *
- * dialcheck tests to see if tty is listed as being a dialup
- * line. If so, a dialup password may be required if the shell
- * is listed as one which requires a second password.
- */
-
- #ifdef DIALUP
- int dialcheck (tty, shell)
- char *tty;
- char *shell;
- {
- char *crypt ();
- char *getpass ();
- struct dialup *dialup;
- char *pass;
- char *cp;
-
- if (! isadialup (tty))
- return (1);
-
- if (! (dialup = getdushell (shell)))
- return (1);
-
- endduent ();
-
- if (dialup->du_passwd[0] == '\0')
- return (1);
-
- if (! (pass = getpass ("Dialup Password:")))
- return (0);
-
- cp = crypt (pass, dialup->du_passwd);
- return (strcmp (cp, dialup->du_passwd) == 0);
- }
- #endif
- SHAR_EOF
- fi
- if test -f 'pwunconv.c'
- then
- echo shar: "will not over-write existing file 'pwunconv.c'"
- else
- cat << \SHAR_EOF > 'pwunconv.c'
- /*
- * pwunconv - restore old password file from shadow password file.
- *
- * Pwunconv copies the password file information from the shadow
- * password file, merging entries from an optional existing shadow
- * file.
- *
- * The new password file is left in npasswd. There is no new
- * shadow file. Password aging information is translated where
- * possible.
- */
-
- #include <sys/types.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <pwd.h>
- #include "config.h"
- #include "lastlog.h"
- #include "shadow.h"
-
- char buf[BUFSIZ];
- char *l64a ();
-
- int main ()
- {
- struct passwd *pw;
- struct passwd *sgetpwent ();
- FILE *pwd;
- FILE *npwd;
- struct spwd *spwd;
- int fd;
-
- if (! (pwd = fopen (PWDFILE, "r"))) {
- perror (PWDFILE);
- return (1);
- }
- unlink ("npasswd");
- if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
- ! (npwd = fdopen (fd, "w"))) {
- perror ("npasswd");
- return (1);
- }
- while (fgets (buf, BUFSIZ, pwd) == buf) {
- buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
-
- if (buf[0] == '#') { /* comment line */
- (void) fprintf (npwd, "%s\n", buf);
- continue;
- }
- if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
- (void) fprintf (npwd, "%s\n", buf);
- continue;
- }
- setspent (); /* rewind shadow file */
-
- if (! (spwd = getspnam (pw->pw_name))) {
- (void) fprintf (npwd, "%s\n", buf);
- continue;
- }
- pw->pw_passwd = spwd->sp_pwdp;
-
- /*
- * Password aging works differently in the two different systems.
- * With shadow password files you apparently must have some aging
- * information. The maxweeks or minweeks may not map exactly.
- * In pwconv we set max == 10000, which is about 30 years. Here
- * we have to undo that kludge. So, if maxdays == 10000, no aging
- * information is put into the new file. Otherwise, the days are
- * converted to weeks and so on.
- */
-
- if (spwd->sp_max > (63*7) && spwd->sp_max < 10000)
- spwd->sp_max = (63*7); /* 10000 is infinity this week */
-
- if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
- spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
- spwd->sp_max /= 7; /* turn it into weeks */
- spwd->sp_min /= 7;
- spwd->sp_lstchg /= 7;
- pw->pw_age = l64a ((long) spwd->sp_lstchg * (64L*64L) +
- spwd->sp_min * (64L) +
- spwd->sp_max);
- } else
- pw->pw_age = (char *) 0;
-
- if (pw->pw_age)
- (void) fprintf (npwd, "%s:%s,%s:%d:%d:%s:%s:%s\n",
- pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
- pw->pw_age, pw->pw_uid, pw->pw_gid,
- pw->pw_gecos, pw->pw_dir,
- pw->pw_shell ? pw->pw_shell:"");
- else
- (void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:%s\n",
- pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
- pw->pw_uid, pw->pw_gid,
- pw->pw_gecos, pw->pw_dir,
- pw->pw_shell ? pw->pw_shell:"");
- }
- endspent ();
-
- if (ferror (npwd)) {
- perror ("pwunconv");
- (void) unlink ("npasswd");
- }
- (void) fclose (npwd);
- (void) fclose (pwd);
- return (0);
- }
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-